﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Cinemachine.Utility;
using Protocols;
using UnityEngine;

public class PlayerMoveMent : MoveCamera
{
    [SerializeField] private float MaximumX = 90; //X轴旋转最大角度
    [SerializeField] private float MinimumX = -90; //X轴旋转最小角度

    [SerializeField] private Animator playeAni; //玩家动画

    [SerializeField]  private VirtualStick virtualStick; //虚拟摇杆
    private Vector3 moveDirection = Vector3.zero; //移动方向 

    public GameClient ClientLogic = null;

    private CharacterController player;
    void Start()
    {
        InitParameter();
        player = GetComponent<CharacterController>();
    }

    //预防抖动 
    void FixedUpdate()
    {
        CurrentMoveSpeed(); //设置当前移动速度
        ControlMove(); //移动控制
        ControlRotate(); //旋转控制
        SendToServer();
    }

    enum Dir
    {
        Forward = 0,
        Back,
        Left,
        Right,
        LeftForward,
        LeftBack,
        RightForward,
        RightBack,
        Other
    }

    private Dir oldDir = Dir.Other;
    private float DirX = 0f;
    private float DirY = 0f;
    private bool Walk = false;

    private float SyncTime = 0;

    private MoveData SyncData = default;
    void SendToServer()
    {
        SyncTime += Time.deltaTime;
        if (SyncTime < 0.1f)
        {
            return;
        }

        SyncTime = 0f;
        

        var trans = player.transform;
        var newData = new MoveData
        {
            move = Walk,
            dir = (short)oldDir,
            pos_x = trans.position.x,
            pos_y = trans.position.y,
            pos_z =  trans.position.z,
            rotate_x =  trans.rotation.x,
            rotate_y = trans.rotation.y,
            rotate_z = trans.rotation.z,
            rotate_w = trans.rotation.w
        };
        if (!SyncData.Compare(newData))
        {
            SyncData = newData;
            
            ClientLogic?.UploadMoveData(newData);
        }
    }

    protected override void ControlMove()
    {
        float _x = 0f, _y = 0f;
        if (virtualStick.isVirtualStick)
        {
            var tmp = virtualStick.GetDirection();
            _x = tmp.x;
            _y = tmp.y;
        }
        else
        {
            _x = Input.GetAxis("Horizontal");
            _y = Input.GetAxis("Vertical");
        }

        moveDirection = new Vector3(_x, 0, _y);

        Walk = moveDirection != Vector3.zero;
        if (Walk)
        {
            var dir = Dir.Forward;
            if (Mathf.Abs(moveDirection.x) < 0.1f)
            {
                if (moveDirection.z > 0)
                {
                    dir = Dir.Forward;
                }
                else
                {
                    dir = Dir.Back;
                }
            }
            else
            {
                if (Mathf.Abs(moveDirection.z) < 0.1f)
                {
                    if (moveDirection.x > 0)
                    {
                        dir = Dir.Right;
                    }
                    else
                    {
                        dir = Dir.Left;
                    }
                }
                else if (moveDirection.z > 0f)
                {
                    if (moveDirection.x > 0)
                    {
                        dir = Dir.RightForward;
                    }
                    else
                    {
                        dir = Dir.LeftForward;
                    }
                }
                else if (moveDirection.z < 0f)
                {
                    if (moveDirection.x > 0)
                    {
                        dir = Dir.RightBack;
                    }
                    else
                    {
                        dir = Dir.LeftBack;
                    }
                }
            }

            if (dir != oldDir)
            {
                oldDir = dir;

                playeAni.SetInteger("dir", (int) dir);
            }

            playeAni.SetBool("walk", true);

            moveDirection = transform.TransformDirection(moveDirection);
            moveDirection *= currentMoveSpeed;
            var dstVal = moveDirection * Time.deltaTime;

            player.Move(dstVal);
        }
        else
        {
            playeAni.SetBool("walk", false);
        }
    }

    protected override void ControlRotate()
    {
        if (Input.GetMouseButton(1))
        {
            Cursor.visible = false; //隐藏指针
            targetAngles.y += Input.GetAxis("Mouse X") * mouseSpeed;
            targetAngles.x -= Input.GetAxis("Mouse Y") * mouseSpeed;
            targetAngles.x = Mathf.Clamp(targetAngles.x, MinimumX, MaximumX); //限制范围 

            currentAngles = Vector3.Lerp(currentAngles, targetAngles, damper * Time.deltaTime);
            CamTrans.localRotation = Quaternion.Euler(new Vector3(currentAngles.x, 0, 0));
            transform.rotation = Quaternion.Euler(new Vector2(0, currentAngles.y));
        }
        else
        {
            Cursor.visible = true; //显示指针
        }

        //抬起鼠标旋转初始化
        if (Input.GetMouseButtonUp(1))
        {
            ResetCamera();
        }
    }

    public override void ResetCamera()
    {
        //刷新当前相机的旋转值
        targetAngles = GetInpectorEulers(transform);
        targetAngles.x = GetInpectorEulers(CamTrans).x;

        targetAngles.x = Mathf.Clamp(targetAngles.x, MinimumX, MaximumX); //限制范围 
        currentAngles = targetAngles;
        //将位置修正
        CamTrans.localRotation = Quaternion.Euler(new Vector3(currentAngles.x, 0, 0));
        transform.rotation = Quaternion.Euler(new Vector2(0, currentAngles.y));
    }

    public Vector3 GetInpectorEulers(Transform transform)
    {
        var transformType = transform.GetType();
        var m_propertyInfo_rotationOrder =
            transformType.GetProperty("rotationOrder", BindingFlags.Instance | BindingFlags.NonPublic);
        var m_OldRotationOrder = m_propertyInfo_rotationOrder.GetValue(transform, null);
        var m_methodInfo_GetLocalEulerAngles =
            transformType.GetMethod("GetLocalEulerAngles", BindingFlags.Instance | BindingFlags.NonPublic);
        var value = m_methodInfo_GetLocalEulerAngles.Invoke(transform, new object[] {m_OldRotationOrder});
        var temp = value.ToString();
        //将字符串第一个和最后一个去掉
        temp = temp.Remove(0, 1);
        temp = temp.Remove(temp.Length - 1, 1);
        //用‘，’号分割
        var tempVector3 = temp.Split(',');
        return new Vector3(float.Parse(tempVector3[0]), float.Parse(tempVector3[1]),
            float.Parse(tempVector3[2]));
    }

    public override void SetCamPos()
    {
        CamTrans.SetParent(transform);
        CamTrans.localPosition = camInitPos;
        CamTrans.localEulerAngles = new Vector3(currentAngles.x, 0, 0);
    }
}
